package downstream

import (
	"context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/status"
	"pay/api/bmember"
	"pay/internal/conf"
	"pay/internal/constant"
	"pay/internal/model"
	"pay/pkg/ecode"
	"pay/pkg/log"
	"pay/pkg/network"
	"pay/pkg/request_key"
	"strconv"
	"time"
)

func newMemberConn(ctx context.Context, addr string) (conn *grpc.ClientConn, err error) {
	dialCtx, cancel := request_key.NewOutGoingContext(ctx, time.Second*1)
	defer cancel()
	conn, err = grpc.DialContext(dialCtx, addr, grpc.WithInsecure(),
		grpc.WithUnaryInterceptor(network.ClientInterceptor(
			"bmember", time.Second*5, memberErrorTranslator)))
	if err != nil {
		err = ecode.AppendMessage(constant.ErrRemoteError, "会员服务地址无法建立有效连接, err=%s", err.Error())
		log.FromContext(ctx).Warnw(err.Error())
		return
	}
	return
}

func memberErrorTranslator(err error) (errCode *ecode.ErrorCode) {
	errCode = ecode.AppendMessage(
		constant.ErrRemoteError, "会员服务调用失败：%s", status.Convert(err).Message())
	return
}

func newMemberClient(ctx context.Context, addr string) (
	client bmember.AssetClient, err error) {
	var conn *grpc.ClientConn
	if conn, err = newMemberConn(ctx, addr); err != nil {
		return
	}
	client = bmember.NewAssetClient(conn)
	return
}

func (d *Downstream) ConsumeBalance(ctx context.Context, order *model.Order) (
	resp *bmember.BalanceInfoReply, err error) {
	memberId, _ := strconv.Atoi(order.OrderKey)
	if d.memberClient == nil {
		if d.memberClient, err = newMemberClient(
			ctx, conf.Conf.Downstream.MemberAddress); err != nil {
			return
		}
	}
	resp, err = d.memberClient.MemberBalancePay(ctx, &bmember.MemberBalancePayReq{
		BrandId:    int64(order.SgId),
		StoreId:    int64(order.PStoreId),
		MemberId:   int64(memberId),
		Amount:     order.Amount,
		PayOrderNo: order.OrderNumber,
		CardInfo:   order.CardInfo,
	})
	return
}

func (d *Downstream) RefundBalance(ctx context.Context, order *model.Order, refund *model.Refund) (
	resp *bmember.BalanceInfoReply, err error) {
	memberId, _ := strconv.Atoi(refund.OrderKey)
	if d.memberClient == nil {
		if d.memberClient, err = newMemberClient(
			ctx, conf.Conf.Downstream.MemberAddress); err != nil {
			return
		}
	}
	resp, err = d.memberClient.MemberBalanceRefund(ctx, &bmember.MemberBalanceRefundReq{
		BrandId:       int64(refund.SgId),
		StoreId:       int64(refund.PStoreId),
		MemberId:      int64(memberId),
		Amount:        refund.Amount,
		RefundOrderNo: refund.OrderNumber,
		PayOrderNo:    order.OrderNumber,
		EmpId:         int64(refund.Operator),
		CardInfo:      order.CardInfo,
		Reason:        refund.RefundReason,
	})
	return
}
